package com.xishu.controller;

import com.xishu.annotation.valid.MethodValidator;
import com.xishu.entity.NameAndId;
import com.xishu.entity.User;
import com.xishu.entity.plat.PrivilegeMapping;
import com.xishu.entity.shop.*;
import com.xishu.foodpanda.FoodPandaImportService;
import com.xishu.response.ResponseData;
import com.xishu.response.ResponseStatus;
import com.xishu.response.VerifyUtil;
import com.xishu.service.*;
import com.xishu.util.ClassUtil;
import com.xishu.util.ServletUtil;
import com.xishu.util.Tools;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Api(description = "菜品管理")
@RestController
public class ItemController implements Tools {
    private CommonService commonService = CommonService.getInstance();
    private ItemService itemService = ItemService.getInstance();
    private static Logger logger = LoggerFactory.getLogger(ItemController.class);

    @ApiOperation(value = "创建菜品")
    @PostMapping(value = ("/user/item"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(checkShop = true, checkShopId = true)
    public ResponseData create(@RequestBody Item item) throws Exception {
        VerifyUtil.verify(() -> item.getShopId() != null, ResponseStatus.SHOP_ID_CAN_NOT_EMPTY);
        VerifyUtil.verify(() -> isNotEmpty(item.getName()) || isNotEmpty(item.getName_zh()) || isNotEmpty(item.getName_en()), ResponseStatus.NAME_CAN_NOT_EMPTY);
        itemService.validItemName(item);

        //如果设置了场景的价格，那么统一价格就不再设置了
        if (isNotEmpty(item.getPriceConfigList()) && item.getPrice() != null) {
            logger.info("will modify price to null");
            item.setPrice(null);
        }

        //不能出现两个场景一样的配置
        if (itemService.hasSameScenePrice(item)) {
            VerifyUtil.throwError(ResponseStatus.CONFIG_WRONG);
        }

        User user = ServletUtil.getUser();
        if (user != null && !getBoolean(user.getAdmin())) {
            //找到当前账户使用的权限组
            List<String> shopPrivilegeList = user.getShopPrivilegeList();
            PrivilegeMapping privilegeMapping = new PrivilegeMapping();
            privilegeMapping.setId(Long.valueOf(shopPrivilegeList.get(0)));
            PrivilegeMapping privilegeMappingInDb = commonService.searchOne(privilegeMapping);
            List<String> privilegeList = privilegeMappingInDb.getPrivilegeList();
            //权限组是否有主菜管理权限
            List<String> privileges = privilegeList.stream().filter(s -> equals("sjcdgl_zcl", s) || equals("sjgl_sjgl", s)).collect(Collectors.toList());
            if (isEmpty(privileges)) {
                Optional<CompanyMainItem> companyMainItemExist = CustomerService.getInstance().isCompanyMainItemExist(item.getCompanyId(), item.getName(), getBoolean(item.getSetMenu()) ? 1 : 0);
                VerifyUtil.verify(companyMainItemExist::isPresent, ResponseStatus.USER_NO_MAIN_ITEM_PRIVILEGE);
            }
        }

        //时价菜不做价格判断
        if (!getBoolean(item.getRealPriceItem())) {
            VerifyUtil.verify(() -> !(getDouble(item.getPrice()) < 0 && isEmpty(item.getPriceConfigList())), ResponseStatus.PRICE_CAN_NOT_EMPTY);
        } else {
            //时价菜，如果前端没有传价格，也没有传场景，那么默认价格是0
            if (isEmpty(item.getPriceConfigList()) && item.getPrice() == null) {
                item.setPrice(0d);
            }
        }

        //不设置，默认上线，设置了，以设置的为准
        if (item.getOnline() == null) {
            item.setOnline(true);
        }

        if (item.getSetMenu() == null) {
            item.setSetMenu(false);
        }

        //如果前端没有设置品类的ID，那么后台设置，设置成0以后，方便B端过滤查询
        if (item.getCatalogId() == null) {
            item.setCatalogId(0l);
        }

        itemService.checkPriceConfigValid(item);
        itemService.checkItemDetailLength(item);

        dealItemDetail(item);
        itemService.dealSetMenuItem(item);

        //只有在创建的时候 ，需要复制数据，修改的时候，不用处理，修改了什么就是什么
        itemService.dealItemZhEn(item);
        itemService.labelListZhEn_create(item);
        itemService.descriptionZhEn_create(item);
        //有同名主菜，就同步当前菜的中英文
        Optional<CompanyMainItem> companyMainItemExist = CustomerService.getInstance().isCompanyMainItemExist(item.getCompanyId(), item.getName(), getBoolean(item.getSetMenu()) ? 1 : 0);
        if (companyMainItemExist.isPresent()) {
            CompanyMainItem mainItem = companyMainItemExist.get();
            if (isNotEmpty(mainItem.getName_en()) && isNotEmpty(mainItem.getName_zh())) {
                item.setName_zh(mainItem.getName_zh());
                item.setName_en(mainItem.getName_en());
            }
        }

        //创建或者修改主菜
        CustomerService customerService = CustomerService.getInstance();
        Long shopId = item.getShopId();
        Shop shop = ShopService.getInstance().findShopById(shopId);
        CompanyMainItem companyMainItem = customerService.getOrCreateCompanyMainItem(shop.getCompanyId(), item.getName(), getBoolean(item.getSetMenu()) ? 1 : 0);
        item.setMainItemId(companyMainItem.getId());

        return CommonService.getInstance().createObject(item, (i) -> {
            try {
                //创建映射关系,只在套餐的时候这样处理，普通菜品保持不变
                if (i.getCatalogId() != null) {
                    //创建新的映射
                    CatalogItemMapping newMapping = new CatalogItemMapping();
                    newMapping.setItemId(i.getId());
                    newMapping.setCatalogId(i.getCatalogId());
                    //如果本次也修改是否上线，那么以本次的为准
                    if (i.getOnline() != null) {
                        newMapping.setOnline(i.getOnline());
                    } else {
                        //如果本次没有修改是否上线，那么以数据库为准
                        newMapping.setOnline(i.getOnline());
                    }

                    //添加名称
                    newMapping.setItemName(i.getName());
                    newMapping.setItemName_en(i.getName_en());
                    newMapping.setItemName_zh(i.getName_zh());

                    Long catalogId = i.getCatalogId();
                    Catalog catalog = CatalogService.getInstance().findCatalogById(catalogId);
                    newMapping.setCatalogName(catalog.getName());
                    newMapping.setCatalogName_zh(catalog.getName_zh());
                    newMapping.setCatalogName_en(catalog.getName_en());
                    newMapping.setImgId(i.getImgId());
                    newMapping.setShopId(i.getShopId());

                    MappingService.getInstance().createCatalogItemMapping(newMapping);
                }

                //修改显示顺序
                itemService.modifyItemShowOrder(item);
            } catch (Exception e) {
                logger.error("e", e);
            }
        });
    }

    @ApiOperation(value = "修改菜品")
    @PutMapping(value = ("/user/item/modify"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(checkShop = true)
    public ResponseData modify(@RequestBody Item item) throws Exception {
        VerifyUtil.verify(() -> item.getId() != null);
        itemService.validItemName(item);
        Integer showOrder = item.getShowOrder();
        boolean isModifyShowOrder = showOrder != null;
        Integer suggestShowOrder = item.getSuggestShowOrder();
        boolean isModifySuggestShowOrder = suggestShowOrder != null;
        Item itemInDb = itemService.findItem(item.getId());
        boolean modifyCatalog = item.getCatalogId() != null && !equals(itemInDb.getCatalogId(), item.getCatalogId());

        itemService.checkPriceConfigValid(item);
        itemService.checkItemDetailLength(item);

        dealItemDetail(item);

        dealItemDetailZhEn(item);

        itemService.dealSetMenuItem(item);

        if (itemService.hasSameScenePrice(item)) {
            logger.info("has the same scene price, will not update price config");
            item.setPriceConfigList(null);
        }

        //管理系统会把所有的参数都带过来，只有B端才会去单独修改
        //这里表示是管理端的请求，管理端不修改余量
        if (item.getCatalogId() != null) {
            item.setLeftCount(null);
            item.setLeftCountShow(null);
        }

        return CommonService.getInstance().updateObject(item, (i) -> {
            try {
                itemService.onlyOnePrice(ItemService.getInstance().findItem(item.getId()));

                //如果修改了映射关系，那么删除映射关系之后再添加映射关系
                if (modifyCatalog) {
                    //删除映射关系
                    CatalogItemMapping catalogItemMapping = new CatalogItemMapping();
                    catalogItemMapping.setItemId(item.getId());
                    catalogItemMapping.setEntity(true);
                    List<CatalogItemMapping> catalogItemMappingList = commonService.searchAll(catalogItemMapping);

                    for (CatalogItemMapping itemMapping : catalogItemMappingList) {
                        itemMapping.setFlagDelete(true);
                        commonService.save(itemMapping);
                    }

                    //创建新的映射
                    CatalogItemMapping newMapping = new CatalogItemMapping();
                    newMapping.setItemId(item.getId());
                    newMapping.setCatalogId(item.getCatalogId());
                    newMapping.setShopId(i.getShopId());

                    //余量不会和修改品类一起出现
                    newMapping.setLeftCount(itemInDb.getLeftCount());
                    newMapping.setSaleOut(itemInDb.getSaleOut());

                    newMapping.setItemName_zh(itemInDb.getName_zh());
                    newMapping.setItemName_en(itemInDb.getName_en());
                    newMapping.setItemName(itemInDb.getName());

                    Long catalogId = item.getCatalogId();
                    Optional<Catalog> catalogOptional = CatalogService.getInstance().findCatalog(catalogId);
                    if (catalogOptional.isPresent()) {
                        Catalog catalog = catalogOptional.get();
                        newMapping.setCatalogName(catalog.getName());
                        newMapping.setCatalogName_zh(catalog.getName_zh());
                        newMapping.setCatalogName_en(catalog.getName_en());
                    } else {
                        logger.info("can not find the catalog for {}", catalogId);
                    }

                    if (item.getImgId() != null) {
                        newMapping.setImgId(item.getImgId());
                    } else {
                        newMapping.setImgId(itemInDb.getImgId());
                    }

                    //如果本次也修改是否上线，那么以本次的为准
                    if (item.getOnline() != null) {
                        newMapping.setOnline(item.getOnline());
                    } else {
                        //如果本次没有修改是否上线，那么以数据库为准
                        newMapping.setOnline(itemInDb.getOnline());
                    }

                    MappingService.getInstance().createCatalogItemMapping(newMapping);
                }

                if (item.getOnline() != null) {
                    //同步修改映射关系
                    CatalogItemMapping catalogItemMapping = new CatalogItemMapping();
                    catalogItemMapping.setItemId(i.getId());
                    List<CatalogItemMapping> catalogItemMappingList = commonService.searchAll(catalogItemMapping);
                    for (CatalogItemMapping mapping : catalogItemMappingList) {
                        mapping.setOnline(item.getOnline());
                        commonService.save(mapping);
                    }
                }

                //同步修改图片ID
                if (item.getImgId() != null) {
                    CatalogItemService.getInstantce().syncItemImgToCatalogItemMapping(item.getId());
                }

                if (item.getSaleOut() != null) {
                    //同步修改映射关系
                    CatalogItemMapping catalogItemMapping = new CatalogItemMapping();
                    catalogItemMapping.setItemId(i.getId());
                    List<CatalogItemMapping> catalogItemMappingList = commonService.searchAll(catalogItemMapping);
                    for (CatalogItemMapping mapping : catalogItemMappingList) {
                        mapping.setSaleOut(item.getSaleOut());
                        commonService.save(mapping);
                    }

                    //如果是售罄，那么套餐也需要同步售罄
                    if (getBoolean(item.getSaleOut())) {
                        itemService.setSetMenuSaleOut(item);
                    } else {
                        itemService.restoreSetMenuSaleOut(item);
                    }

                    //同步处理foodpanda里面的状态
                    FoodPandaImportService.getInstance().itemAvailable(item.getId());
                }

                //同步修改映射的余量
                if (item.getLeftCount() != null) {
                    logger.info("will modify mapping left count {}", item.getId());
                    CatalogItemMapping catalogItemMapping = new CatalogItemMapping();
                    catalogItemMapping.setItemId(i.getId());

                    List<CatalogItemMapping> catalogItemMappingList = commonService.searchAll(catalogItemMapping);

                    for (CatalogItemMapping mapping : catalogItemMappingList) {
                        mapping.setLeftCount(item.getLeftCount());

                        if (item.getLeftCount() != null) {
                            catalogItemMapping.setLeftCountShow(item.getLeftCount() + "");
                        } else {
                            catalogItemMapping.setLeftCountShow(null);
                        }
                        commonService.save(mapping);
                    }
                }

                //如果要修改的规格，跟普通的套餐规格一样的
                //同步修改其它套餐里面有这个菜的规格
                itemService.modifyRelateSetMenuItem(i.getId());

                //修改了排序的顺序，样那么需要将所有的菜品查询出来，过滤当该菜一的顺序的菜，如果存在，则比该菜的顺序大于等于的菜的顺序均加1再保存
                if (isModifyShowOrder || isModifySuggestShowOrder) {
                    itemService.modifyItemShowOrder(item);
                }

//                itemService.itemNameSyncToOther(item.id);
//                itemService.syncItemNameInSetMenu(itemService.findItem(item.id));
            } catch (Exception e) {
                logger.error("e", e);
            }
        });
    }

    /**
     * 处理国际化
     * 如果只传了中文，那么把英文读出来，再把英文写回去
     * 英文同理
     *
     * @param item
     */
    private void dealItemDetailZhEn(Item item) throws Exception {
        if (isEmpty(item.getItemDetailList())) {
            logger.info("detail list is empty");
            return;
        }

        Item itemInDb = itemService.findItem(item.getId());
        List<ItemDetail> itemDetailListInDb = itemInDb.getItemDetailList();

        List<ItemDetail> itemDetailList = item.getItemDetailList();
        List<NameAndPrice> nameAndPriceListInDb = getList(item.getItemDetailList()).stream().flatMap(p -> p.getNameAndPriceList().stream()).collect(Collectors.toList());

        for (ItemDetail itemDetail : itemDetailList) {
            Optional<ItemDetail> itemDetailOptional = itemDetailListInDb.stream().filter(p -> equals(p.getId(), itemDetail.getId())).findAny();
            if (itemDetailOptional.isPresent()) {

                if (isEmpty(itemDetail.getName())) {
                    itemDetail.setName(itemDetailOptional.get().getName());
                }

                if (isEmpty(itemDetail.getName_zh())) {
                    itemDetail.setName_zh(itemDetailOptional.get().getName_zh());
                }

                if (isEmpty(itemDetail.getName_en())) {
                    itemDetail.setName_en(itemDetailOptional.get().getName_en());
                }
            }

            List<NameAndPrice> nameAndPriceList = getList(itemDetail.getNameAndPriceList());
            for (NameAndPrice nameAndPrice : nameAndPriceList) {
                Optional<NameAndPrice> nameAndPriceOptional = nameAndPriceListInDb.stream().filter(p -> equals(p.getId(), nameAndPrice.getId())).findAny();
                if (nameAndPriceOptional.isPresent()) {

                    if (isEmpty(nameAndPrice.getName())) {
                        nameAndPrice.setName(nameAndPriceOptional.get().getName());
                    }

                    if (isEmpty(nameAndPrice.getName_zh())) {
                        nameAndPrice.setName_zh(nameAndPriceOptional.get().getName_zh());
                    }

                    if (isEmpty(nameAndPrice.getName_en())) {
                        nameAndPrice.setName_en(nameAndPriceOptional.get().getName_en());
                    }
                }
            }
        }
    }

    @ApiOperation(value = "查询菜品")
    @PutMapping(value = ("/user/item"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData search(@RequestBody Item item) throws Exception {
        if (isNotEmpty(item.getCatalogIdList())) {
            List<Long> itemIdList = itemService.findItemByCatalogList(item.getCatalogIdList());

            if (isEmpty(itemIdList)) {
                return commonService.createResponse(new ArrayList<>());
            }

            //通过ID列表重新查询
            Item reqItem = new Item();
            reqItem.setIds(itemIdList);
            reqItem.setName_zh(item.getName_zh());
            reqItem.setName_en(item.getName_en());

            //再带上分页
            reqItem.setPageNumber(item.getPageNumber());
            reqItem.setPageSize(item.getPageSize());
            reqItem.setSetMenu(item.getSetMenu());
            reqItem.setEntity(true);
            if (getBoolean(item.getFilterSuggestion())) {
                reqItem.setFilterSuggestion(true);
            }
            item = reqItem;
        }

        Item requestItem = item;

        return CommonService.getInstance().searchResponse(item, (itemInDb) -> {
            if (itemInDb.getLeftCount() != null) {
                itemInDb.setLeftCountShow(itemInDb.getLeftCount() + "");
            }

            //处理套餐的默认值
            if (getBoolean(itemInDb.getSetMenu())) {
                for (SetMenuOneItem setMenuOneItem : getList(itemInDb.getSetMenuOneItemList())) {
                    commonService.dealDefaultValueWithAnnotation(setMenuOneItem);
                }
            }

            try {
                itemService.onlyOnePrice(itemInDb);
            } catch (Exception e) {
                logger.error("e", e);
            }
        }, (itemList) -> {
            itemList = itemList.stream().map(p -> {
                try {
                    return (Item) ClassUtil.clone(p);
                } catch (Exception e) {
                    logger.error("e", e);
                    return null;
                }
            }).filter(p -> p != null).collect(Collectors.toList());

            itemList.forEach(itemTmp -> {
                //查询商品列表的时候，如果需要实时价格
                if (getBoolean(requestItem.getQueryRealTimePrice())) {
                    try {
                        itemTmp.setFilterSceneId(requestItem.getFilterSceneId());
                        itemService.setRealTimePrice(itemTmp);
                    } catch (Exception e) {
                        logger.error("e", e);
                    }
                }
            });

            List<Item> filterItemSceneList = itemList;

            if (getBoolean(requestItem.getSuggestion()) && requestItem.getFilterSceneId() != null) {
                filterItemSceneList = itemList.stream().filter(tmpItem -> isNotEmpty(tmpItem.getSceneList()) && tmpItem.getSceneList().stream().filter(p -> equals(p.getId(), requestItem.getFilterSceneId())).findAny().isPresent()).collect(Collectors.toList());
            }

            filterItemSceneList = itemService.filterItemSceneList(requestItem.getFilterSceneId(), filterItemSceneList);

            List<Item> itemFilterPriceList = filterItemSceneList.stream().filter(item_tmp -> getBoolean(item_tmp.getRealPriceItem()) || getDouble(item_tmp.getPrice()) >= 0).collect(Collectors.toList());
            logger.info("itemFilterPriceList size is {}", itemFilterPriceList.size());
            return itemFilterPriceList;
        });
    }

    @ApiOperation(value = "删除菜品")
    @DeleteMapping(value = ("/user/item"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(checkShop = true)
    public ResponseData delete(@RequestBody Item item) throws Exception {
        VerifyUtil.verify(() -> item.getId() != null || isNotEmpty(item.getIds()));

        return CommonService.getInstance().delete(item, true, (i) -> {
            try {
                //同步删除映射关系
                CatalogItemMapping catalogItemMapping = new CatalogItemMapping();
                catalogItemMapping.setItemId(i.getId());
                List<CatalogItemMapping> catalogItemMappingList = commonService.searchAll(catalogItemMapping);

                for (CatalogItemMapping mapping : catalogItemMappingList) {
                    mapping.setOnline(false);
                    mapping.setFlagDelete(true);
                    commonService.save(mapping);
                }

                //删除套餐关联菜品
                itemService.deleteRelateSetMenuItem(i.getId());
                //删除foodPanda里面的菜和套餐
                itemService.deleteFoodPandaRelateSetMenuItem(i.getId());
            } catch (Exception e) {
                logger.error("e", e);
            }
        });
    }

    @ApiOperation(value = "清空菜品的余量设置")
    @PutMapping(value = ("/user/item/left/count"), produces = ("application/json;charset=UTF-8"))
    public ResponseData cancelSaleOut(@RequestBody Item reqItem) throws Exception {
        Item item = itemService.findItem(reqItem.getId());
        item.setLeftCount(null);
        item.setLockCount(null);
        commonService.save(item);

        //同步更新映射关系
        logger.info("will modify mapping left count {}", item.getId());
        CatalogItemMapping catalogItemMapping = new CatalogItemMapping();
        catalogItemMapping.setItemId(item.getId());

        List<CatalogItemMapping> catalogItemMappingList = commonService.searchAll(catalogItemMapping);

        for (CatalogItemMapping mapping : catalogItemMappingList) {
            logger.info("update mapping id {} to null", mapping.getId());
            mapping.setLeftCount(null);
            commonService.save(mapping);
        }

        return commonService.createResponse(item);
    }

    /**
     * 处理细节部分，如果名称为空，则不添加
     * 如果没有索引，那么添加索引
     *
     * @param item
     * @throws Exception
     */
    private void dealItemDetail(@RequestBody Item item) throws Exception {
        //规格处理，如果有规格对象，但是规格的名称，以及规格下面的细节名称没有填写，忽略掉
        if (isNotEmpty(item.getItemDetailList())) {
            //如果只有一条，并且name值为空，那么设置空数据
            if (item.getItemDetailList().size() == 1) {
                ItemDetail itemDetail = item.getItemDetailList().get(0);

                if (isEmpty(itemDetail.getName()) && isEmpty(itemDetail.getName_zh()) && isEmpty(itemDetail.getName_en())) {
                    logger.info("empty list");
                    item.setItemDetailList(new ArrayList<>());
                    return;
                }
            }


            List<ItemDetail> itemDetailList = item.getItemDetailList();
            List<ItemDetail> filterItemDetailList = itemDetailList.stream().filter(p -> {
                if (isEmpty(p.getName()) && isEmpty(p.getName_zh()) && isEmpty(p.getName_en())) {
                    logger.info("name is empty");
                    return false;
                }

                if (isEmpty(p.getNameAndPriceList())) {
                    logger.info("name and price is empty");
                    return false;
                }

                for (NameAndPrice nameAndPrice : p.getNameAndPriceList()) {
                    if (isEmpty(nameAndPrice.getName()) && isEmpty(nameAndPrice.getName_en()) && isEmpty(nameAndPrice.getName_zh())) {
                        logger.info("item and price name is empty");
                        return false;
                    }
                }

                return true;
            }).collect(Collectors.toList());

            if (isEmpty(filterItemDetailList)) {
                item.setItemDetailList(null);
            } else {
                item.setItemDetailList(filterItemDetailList);
            }
        }

        //添加索引字段
        itemService.addDetailIndex(item);

        //处理必选，多选
        List<ItemDetail> itemDetailList = getList(item.getItemDetailList());
        for (ItemDetail itemDetail : itemDetailList) {
            if (getLong(itemDetail.getMinSelect()) > 0) {
                itemDetail.setRequired(true);
            }

            if (getLong(itemDetail.getMinSelect()) > 1) {
                itemDetail.setMulti(true);
            }
        }
    }

}
